using System;
using System.Collections.Generic;
using System.Linq;
using AutoTest.Core.Domain.TestQueuing;
using SharpTestsEx;

namespace AutoTest.Core.Infrastructure.Messaging
{
    public class MessageBusTestDouble: IMessageBus
    {
        public List<PublishedMessage> PublishedMessages { get; private set; }

        public MessageBusTestDouble()
        {
            PublishedMessages = new List<PublishedMessage>();
        }

        public void Publish<T>(object sender, T message)
        {
            PublishedMessages.Add(new PublishedMessage {Sender = sender, Message = message});
        }

        public void AssertWasPublished<T>(object sender, Predicate<T> messageSpecification)
        {
            var message = PublishedMessages
                .Where(m => m.Sender == sender)
                .Where(m => m.Message is T && messageSpecification((T) m.Message))
                .FirstOrDefault();
            message.Should(" Message was not published.").Not.Be.Null();
        }

        public void AssertWasNotPublished<T>(object sender, Predicate<T> messageSpecification)
        {
            var message = PublishedMessages
                .Where(m => m.Sender == sender)
                .Where(m => m.Message is T && messageSpecification((T)m.Message))
                .FirstOrDefault();
            message.Should(" Message was published.").Be.Null();
        }

        public void AssertWasNotPublished(object sender)
        {
            var message = PublishedMessages
                .Where(m => m.Sender == sender)
                .FirstOrDefault();
            message.Should(" Message was published.").Be.Null();
        }

        public class PublishedMessage
        {
            public object Sender { get; set; }
            public object Message { get; set; }
        }

        public void AssertWasPublishedOnce<T>(object sender, Predicate<T> messageSpecification)
        {
            var timesPublished = PublishedMessages
                .Where(m => m.Sender == sender)
                .Where(m => m.Message is T && messageSpecification((T)m.Message))
                .Count();
            timesPublished.Should().Be.EqualTo(1);
        }
    }
}